Skip to content

Implement GString concatenation operator #1117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

PierceLBrooks
Copy link

This will allow for users to add together their GString references with plus sign notation from within the Rust runtime of a gdextension, like so:

let concat = &GString::from("12") + &GString::from(" is a ") + &GString::from("true") + &GString::from(" number");

@Bromeon Bromeon added feature Adds functionality to the library c: core Core components labels Apr 6, 2025
@Bromeon
Copy link
Member

Bromeon commented Apr 6, 2025

Hi, and thanks for your contribution! 👍

I'm not sure the + operator is something I want to add to godot-rust. Your example is rather verbose and encourages inefficient code by creating lots of temporary allocations/conversions that are then immediately thrown away.

Instead of

let a = GString::from(" is a ");
let b = GString::from("true");
let concat = &GString::from("12") + &a + &b + &GString::from(" number");

one can write

let a = "is a";
let b = true;
let concat: GString = format!("12{a}{b} number").into();

Which has multiple advantages:

  • more readable
  • more performant (Rust string is concatenated, only one Rust->Godot conversion)
  • works with any concatenation type (here bool), not just other GStrings.

@PierceLBrooks
Copy link
Author

Hi @Bromeon,

The verbosity of my example usage was mostly just due to to mirroring the logic originally employed by the utilities_test.rs unit test file's utilities_str function.

In regard to performance, I do understand your concerns. My overall intention is to allow for a less lexically frictional experience for those adjusting to Rust from GDScript. Though operator overloading in this way may not be strictly so idiomatic for the avid Rust user, it does offer marginally greater parity with GDScript's syntax, which if that is not a primary priority for the GDExt project, then the closure of this pull request may indeed be appropriate.

@PierceLBrooks
Copy link
Author

Please let me know if PierceLBrooks@7acaafc helps at all to minimize any of your performance concerns.

@Bromeon
Copy link
Member

Bromeon commented Apr 10, 2025

Please let me know if PierceLBrooks@7acaafc helps at all to minimize any of your performance concerns.

Using + still means that only 2 operands can be passed at a time, so a + b + c + d amounts to 3 str() roundtrips via FFI, plus the involved variant conversions and marshalling.

Using a single str() call is strictly better here. It also accepts non-string arguments.


In regard to performance, I do understand your concerns. My overall intention is to allow for a less lexically frictional experience for those adjusting to Rust from GDScript. Though operator overloading in this way may not be strictly so idiomatic for the avid Rust user, it does offer marginally greater parity with GDScript's syntax, which if that is not a primary priority for the GDExt project, then the closure of this pull request may indeed be appropriate.

I understand, but in godot-rust we need to strike a balance between what's idiomatic in Rust and what's idiomatic in Godot. The + operator just has too many disadvantages... and it's not even great in GDScript because it only supports string operands (I almost always use str myself).

The str function is already available, as a relatively straightforward migration path from GDScript to Rust. I agree it could be more discoverable, which is something I plan to address in godot-rust/book#11.

Potentially, we could also think about providing a format-style macro that internally calls str and can be used like this:

let a = "is a";
let b = true;
let concat = godot_str!("12{a}{b} number");

What do you think about this?

@Bromeon
Copy link
Member

Bromeon commented Apr 12, 2025

@PierceLBrooks would you be willing to change this PR to implement godot_str! as described above?

There is some prior art with the godot_print! macro; I could imagine the implementation to look very similar.

@PierceLBrooks
Copy link
Author

@Bromeon yes, I believe I will have enough free time to make a proper attempt at doing so before the weekend is over here. Thanks for the opportunity!

@Bromeon
Copy link
Member

Bromeon commented Apr 13, 2025

Thanks to you! 😊

As mentioned, the already existing godot_print! macro could be a good start, as it follows the same principle. Let me know if you need any support!

@Bromeon
Copy link
Member

Bromeon commented Apr 19, 2025

@PierceLBrooks have you had a chance to look into this yet? Let us know in case you get stuck somewhere! 🙂

@Bromeon Bromeon added this to the 0.3.x milestone Apr 19, 2025
@PierceLBrooks
Copy link
Author

@Bromeon , yes I have taken a look this week and will likely have conclusive progressive by the end of this weekend. The past week ended up being a little more chaotic than originally anticipated :P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: core Core components feature Adds functionality to the library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants